Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 19 Weitere Steuerelemente
  gp 19.1 Bildlaufleisten mit »HScrollBar« und »VScrollBar«
  gp 19.2 Schieberegler mit der Klasse »TrackBar«
  gp 19.3 Das »ProgressBar«-Steuerelement
  gp 19.4 Drehfeld-Steuerelemente (»UpDown«-Steuerelemente)
    gp 19.4.1 Das »NumericUpDown«-Steuerelement
    gp 19.4.2 Das »DomainUpDown«-Steuerelement
  gp 19.5 Das »Timer«-Steuerelement
  gp 19.6 Die Klasse »ErrorProvider«
  gp 19.7 Steuerelemente für die Datums- und Zeitangabe
    gp 19.7.1 Das Steuerelement »MonthCalendar«
    gp 19.7.2 Das Steuerelement »DateTimePicker«
  gp 19.8 Das »Panel«-Steuerelement
  gp 19.9 Das Steuerelement »NotifyIcon«
  gp 19.10 Bildanzeige mit »PictureBox«
  gp 19.11 Eine Liste mit Symbolen mit »ImageList« bereitstellen
    gp 19.11.1 Die Eigenschaften der Klasse »ImageList«
    gp 19.11.2 Die Bildliste füllen
  gp 19.12 Registerkarten mit »TabControl«
    gp 19.12.1 Die Klasse »TabControl«
    gp 19.12.2 Objekte vom Typ »TabPage«
  gp 19.13 Das »TreeView«-Steuerelement
    gp 19.13.1 Knotenpunkte im »TreeView« definieren
    gp 19.13.2 Eigenschaften des »TreeView«-Steuerelements
    gp 19.13.3 Die Unterstützung der Entwicklungsumgebung
    gp 19.13.4 Die Ereignisse des »TreeView«-Steuerelements
    gp 19.13.5 Weitere Eigenschaften und Methoden des »TreeView«-Objekts
    gp 19.13.6 Eigenschaften und Methoden des »TreeNode«-Objekts
    gp 19.13.7 Beispiel zum Einlesen der Verzeichnisstruktur
  gp 19.14 Die beiden »Splitter«-Steuerelemente
    gp 19.14.1 Das Steuerelement »Splitter«
    gp 19.14.2 Das Steuerelement »SplitContainer«
  gp 19.15 Das »ListView«-Steuerelement
    gp 19.15.1 Die Klassen des »ListView«-Steuerelements
    gp 19.15.2 Die Eigenschaften der »ListView«
    gp 19.15.3 Listenelemente vom Typ »ListViewItem«
    gp 19.15.4 Das Element »ListViewSubItem«
    gp 19.15.5 Der Typ »ColumnHeader«
    gp 19.15.6 Listenelemente Gruppen zuordnen
    gp 19.15.7 Sortierung der Spalten
    gp 19.15.8 Listenelemente ändern
    gp 19.15.9 Beispielanwendung
  gp 19.16 BackGroundWorker


Galileo Computing

19.9 Das Steuerelement »NotifyIcon«  toptop

Mit dem Steuerelement NotifyIcon können Sie ein Symbol im so genannten System Tray der Taskleiste anzeigen. Das System Tray wird insbesondere von Programmen benutzt, die zwar geladen sind, aber nur im Hintergrund arbeiten und (zunächst) kein sichtbares Fenster haben.

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 19.12   Das »System Tray« der Taskleiste

Die mit den Symbolen im System Tray verbundenen Programme weisen einige besondere Merkmale auf:

gp  Mit einem Doppelklick auf das Symbol öffnet sich ein Fenster.
gp  Das Symbol verfügt über ein Kontextmenü, das mindestens ein Menüelement zum Schließen der Anwendung anbietet.
gp  Wird das Fenster, das per Doppelklick auf das Symbol geöffnet worden ist, geschlossen, bleibt das Symbol im System Tray weiterhin sichtbar und aktiv.
gp  Manche Anwendungen öffnen dasselbe Fenster mehrfach, wenn wiederholt auf das Symbol geklickt wird.

Um diese Verhaltensweisen zu programmieren, müssen Sie nur vier Eigenschaften des NotifyIcon-Objekts festlegen und darüber hinaus einen Ereignishandler implementieren. Mit der Eigenschaft Icon wird das Symbol festlegt. Die Eigenschaft Visible bestimmt, ob das Symbol im System Tray angezeigt wird, und die Eigenschaft Text beschreibt den QuickInfo-Text, der angezeigt wird, wenn sich der Mauszeiger über dem Symbol befindet. Die vierte und letzte Eigenschaft ist ContextMenu, der die Referenz auf ein Kontextmenü übergeben wird.

Im .NET Framework 2.0 wurde NotifyIcon um die Bereitstellung von Sprechblasen erweitert. Üblicherweise werden diese für eine gewisse Zeitspanne angezeigt, wenn sich das Symbol erstmalig im System Tray ablegt. Hier steuern drei Eigenschaften das Erscheinungsbild der Sprechblase:

gp  BalloonTipIcon
gp  BalloonTipText
gp  BalloonTipTitle

BallonTipText ordnen Sie den Text zu, der in der Sprechblase angezeigt werden soll. Vergeben Sie einen Titelleistentext in BalloonTipTitle, wird in der Sprechblase zusätzlich eine Schließen-Schaltfläche angeboten. Haben Sie einen Titelleistentext, steht Ihnen auch noch die Option offen, zusätzlich ein Symbol anzuzeigen. Hier sind Sie jedoch auf die Auswahl zwischen Info, Warning und Error eingeschränkt.

Automatisch wird die Sprechblase nicht angezeigt. Wenn Sie eine wünschen, rufen Sie die Methode ShowBalloonTip auf und übergeben dieser als Argument die Zeitspanne, in der die Sprechblase angezeigt wird, z.B.:


notifyIcon1.ShowBalloonTip(10);

Laut .NET-Dokumentation soll die Angabe in Millisekunden sein. Das stimmt aber anscheinend nicht, es handelt sich wohl tatsächlich um Sekunden.

Sprechblasen werden gewöhnlich nach dem Laden der Anwendung informationshalber angezeigt. Für den Aufruf der ShowBalloonTip-Methode bietet sich daher der Konstruktor der Form an, die das System-Tray-Symbol repräsentiert.

Der minimale und maximale mögliche Zeitwert wird vom Betriebssystem vorgegeben und liegt normalerweise, betriebssystemabhängig, zwischen 10 und 30 Sekunden. Wenn der Benutzer außerdem keine Aktionen mit der Maus oder der Tastatur ausführt, berücksichtigt das System die Zeitangabe nicht.

Üblicherweise reagieren die Symbole im System Tray auf einen Doppelklick. Deshalb sollte das Ereignis DoubleClick in jedem Fall bei einem Ereignishandler registriert werden.

Beispielprogramm

Das folgende Beispielprogramm weist alle typischen Verhaltensmerkmale auf, die von einer im Hintergrund arbeitenden Anwendung erwartet werden.

Nach dem Start wird zunächst nur das Symbol im System Tray angezeigt. Erst auf Doppelklick hin öffnet sich ein Fenster, das in einem Label-Steuerelement die aktuelle Uhrzeit anzeigt, die jede Sekunde aktualisiert wird. Dazu enthält die Form ein Timer-Steuerelement. Es können mehrere Fenster durch wiederholten Doppelklick geöffnet werden. Jedes der Fenster kann geschlossen werden, ohne dass gleichzeitig auch die Anwendung beendet wird. Beendet wird die Anwendung nur über das Kontextmenü des Symbols.


// --------------------------------------------------------------
// Beispiel: ...\Kapitel 19\NotifyIconDemo
// --------------------------------------------------------------
static class Program {
  static void Main() {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Form1 frm = new Form1();
    Application.Run();
  }
}
 
public partial class Form1 : Form {
  public Form1() {
    InitializeComponent();
    notifyIcon1.ShowBalloonTip(10);
  }
  private void notifyIcon1_DoubleClick(object sender, EventArgs e) {
    Form1 frm1 = new Form1();
    frm1.notifyIcon1.Visible = false;
    frm1.label1.Text = DateTime.Now.ToLongTimeString();
    frm1.Show();
    frm1.Activate();
}
 
  private void timer1_Tick(object sender, EventArgs e) {
    label1.Text = DateTime.Now.ToLongTimeString();
  }
  private void mnuBeenden_Click(object sender, EventArgs e) {
    this.notifyIcon1.Icon = null;
    Application.Exit();
  }
}

Bereits der Start der Anwendung in Program.Main ist anders, als wir es bisher gemacht haben:


Form1 frm = new Form1();
Application.Run();

Wir instanziieren die Form-Klasse, allerdings nicht in der von der Methode Run eröffneten Nachrichtenschleife. Damit vermeiden wir, dass das Fenster nach dem Start der Anwendung automatisch angezeigt wird, denn wir haben zuerst nur Interesse am in der Form enthaltenen NotifyIcon-Objekt, das trotzdem im System Tray zu sehen ist.

Im Ereignis DoubleClick des NotifyIcon-Objekts wird die Form-Klasse erneut instanziiert. Das hat einen bestimmten Grund. Würden wir nämlich zur Anzeige die Fensterinstanz benutzen, die auch für die Anzeige des Symbols verantwortlich ist, würde das Schließen des Fensters auch das Löschen der Symbolanzeige im System Tray nach sich ziehen.

In der neuen Form-Instanz wird die Eigenschaft Visible des NotifyIcon-Objekts auf false festgelegt, damit bei einem Doppelklick auf das Symbol kein weiteres Symbol im System Tray angezeigt wird. Die letzte Anweisung im Ereignishandler ist der Aufruf der Methode Activate, um das Fenster zu aktivieren.

Geschlossen wird die Anwendung über das Kontextmenü des NotifyIcon-Objekts. Dazu wird die Exit-Methode der Klasse Application aufgerufen. Zuvor muss der Eigenschaft Icon des NotifyIcon-Objekts null übergeben werden. Ohne diese Anweisung würde das Symbol nach dem Beenden der Anwendung im System Tray weiterhin sichtbar sein.

Sicherstellen, dass eine Anwendung nur einmal gestartet wird

Unser Beispielprogramm NotifyIcon-Demo ist ein typisches Beispiel für Programme, die nur einmal gestartet werden sollten. Doch wie können wir den Mehrfachstart der Anwendung verhindern? Es gibt mehrere Lösungsansätze, wobei den meisten aber der Nachteil anhaftet, nicht eindeutig zu sein. Beispielsweise könnten Sie die einem laufenden Prozess zugrunde liegende EXE-Datei abfragen. Gibt es aber eine zweite, gleichnamige Datei auf dem Rechner, scheidet dieser Ansatz bereits aus.

Um zu einer eindeutigen Lösung zu kommen, müssen wir einem laufenden Thread ein Objekt anheften, das selbst in der Lage ist, den Startvorgang zu kontrollieren. Hier bietet sich die Klasse Mutex aus dem Namespace System.Threading an. Grundsätzlich ist ein Mutex ein Systemobjekt und dient dazu, den Zugriff von zwei oder mehr Threads auf eine Ressource zu synchronisieren, so dass nur ein Thread die Ressource nutzen kann. In unserem Fall wäre die Ressource die Anwendung selbst. Wenn ein Thread einen Mutex erhält, wird ein zweiter Thread, der diesen Mutex abruft, so lange angehalten, bis der erste Thread den Mutex freigibt.

Mit der Methode WaitOne kann ein Thread den Besitz eines Mutex anfordern. Die Methode liefert einen booleschen Wert zurück. Er ist true, wenn das Mutex-Objekt von keinem anderen Thread blockiert wird. Dann übernimmt das Mutex-Objekt den Thread und sperrt die Ressource. Mit der Methode ReleaseMutex wird die gesperrte Ressource durch den Mutex wieder freigegeben. Erst danach können andere Threads mit WaitOne die Ressource für sich beanspruchen.

Den Mechanismus eines Mutex für unsere Zwecke zu nutzen ist sehr einfach. Dazu instanziieren wir die Klasse mit einem passenden Konstruktor, dem für das Mutex-Objekt ein eindeutiger Name übergeben wird:


public Mutex(bool, string);

Im ersten Argument kann man festlegen, ob das Objekt den Thread sofort blockieren soll. Da wir das aber mit WaitOne steuern wollen, übergeben wir false:


Mutex mutex = new Mutex(false, "eine eindeutige Zeichenfolge");

Mit WaitOne müssen wir nun versuchen, in den Besitz des Mutex zu gelangen. Die Methode ist überladen. Verwendet man die parameterlose Variante, wartet der Aufrufer bei Nichterhalt des Mutex so lange, bis das Objekt vom anderen Prozess wieder freigegeben wird. In unserem Fall hätte das zur Folge, dass die laufende Anwendung den wiederholten Startversuch so lange blockiert, bis die laufende Anwendung ReleaseMutex aufruft oder beendet wird. Anschließend startet die Anwendung sofort erneut. Das ist es aber nicht, was wir wollen. Vielmehr streben wir an, den wiederholten Startversuch sofort zu beenden, ohne dass sich dieser in eine Warteschlange einreiht.

Die Überladung, der ein Integer und ein boolescher Wert übergeben wird, eignet sich für unsere Absicht bestens:


public virtual bool WaitOne(int, bool);

Im ersten Argument wird eine Zeitspanne in Millisekunden angegeben, die gewartet werden soll, bis das Mutex-Objekt freigegeben wird. Das zweite Argument ist für unsere Belange bedeutungslos.

Nun können wir alle Erkenntnisse zusammenfassen. Den Code, der das Startverhalten steuert, muss in der Methode Main implementiert werden.


// Änderung der Methode Main im Projekt NotifyIcon-Demo
static void Main() {
  Mutex mutex = new Mutex(false, Application.ProductName + "xyz_123");
  if(mutex.WaitOne(0, false)) {
    Form1 frm = new Form1();
    Application.Run();
  }
  MessageBox.Show("Ende der Vorstellung");
}

Zuerst beschaffen wir uns das Mutex-Objekt unter Übergabe eines eindeutigen Namens. Es bietet sich dabei an, sich mit Application.ProductName den Anwendungsbezeichner zu besorgen und diesen, gewissermaßen zur Sicherheit, mit einer Erweiterung zu ergänzen, denn es wäre durchaus denkbar, dass sich zufälligerweise auf dem Rechner eine Anwendung gleichen Namens befindet. Anschließend erfolgt der Aufruf der Methode WaitOne. Ist das Mutex-Objekt nicht gesperrt, liefert der Methodenaufruf true, und sowohl die Form als auch die Nachrichtenschleife können initialisiert werden. Ist der Rückgabewert jedoch false, wird noch eine informative Meldung angezeigt und anschließend die Anwendung beendet.

 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de